package stone926.mods.more_enchantments.screen;

import net.minecraft.block.BlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.potion.PotionUtil;
import net.minecraft.screen.ForgingScreenHandler;
import net.minecraft.screen.ScreenHandlerContext;
import net.minecraft.screen.ScreenHandlerType;
import org.jetbrains.annotations.Nullable;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;

import java.util.ArrayList;
import java.util.List;

public class EffectAdderScreenHandler extends ForgingScreenHandler {

  public EffectAdderScreenHandler(@Nullable ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) {
    super(type, syncId, playerInventory, context);
  }

  @Override
  protected boolean canTakeOutput(PlayerEntity player, boolean present) {
    return true;
  }

  @Override
  protected void onTakeOutput(PlayerEntity player, ItemStack stack) {
    input.setStack(0, ItemStack.EMPTY);
    input.setStack(1, ItemStack.EMPTY);
  }

  @Override
  protected boolean canUse(BlockState state) {
    return state.isOf(MoreEnchantmentsMod.EFFECT_ADDER);
  }

  @Override
  public void updateResult() {
    ItemStack firstStack = input.getStack(0).copy();
    if (firstStack.isEmpty()) {
      this.output.setStack(0, ItemStack.EMPTY);
    } else {
      ItemStack secondStack = input.getStack(1);
      int swordWithEffectLvl = EnchantmentHelper.getLevel(MoreEnchantmentsMod.SWORD_WITH_EFFECT, firstStack);
      boolean isSecondStackPotion = secondStack.isOf(Items.POTION);
      boolean isSecondStackSplashPotion = secondStack.isOf(Items.SPLASH_POTION);
      boolean isSecondStackLingeringPotion = secondStack.isOf(Items.LINGERING_POTION);
      boolean isSecondStackAKindOfPotion = isSecondStackPotion || isSecondStackLingeringPotion || isSecondStackSplashPotion;
      if (swordWithEffectLvl > 0) {

        if (isSecondStackAKindOfPotion) {
          List<StatusEffectInstance> addedEffects = PotionUtil.getPotionEffects(secondStack);
          List<StatusEffectInstance> originalEffects = PotionUtil.getCustomPotionEffects(firstStack);
          PotionUtil.setCustomPotionEffects(firstStack, mergeEffectList(originalEffects, addedEffects));

          NbtCompound nbtCompound = firstStack.getOrCreateNbt();
          NbtList areaEffectsNbtList = nbtCompound.getList(MoreEnchantmentsMod.MOD_ID + ":areaEffects", 10);
          NbtList splashEffectsNbtList = nbtCompound.getList(MoreEnchantmentsMod.MOD_ID + ":splashEffects", 10);

          if (isSecondStackLingeringPotion) {

            addedEffects.forEach(effect -> areaEffectsNbtList.add(effect.writeNbt(new NbtCompound())));

            nbtCompound.putBoolean(MoreEnchantmentsMod.MOD_ID + ":isFromLingeringPotion", true);
            nbtCompound.put(MoreEnchantmentsMod.MOD_ID + ":areaEffects", areaEffectsNbtList);

          } else if (isSecondStackSplashPotion) {

            addedEffects.forEach(effect -> splashEffectsNbtList.add(effect.writeNbt(new NbtCompound())));

            nbtCompound.putBoolean(MoreEnchantmentsMod.MOD_ID + ":isFromSplashPotion", true);
            nbtCompound.put(MoreEnchantmentsMod.MOD_ID + ":splashEffects", splashEffectsNbtList);

          }

          this.output.setStack(0, firstStack);
        }

        this.sendContentUpdates();
      }
    }
  }

  private List<StatusEffectInstance> mergeEffectList(List<StatusEffectInstance> origin, List<StatusEffectInstance> add) {
    List<StatusEffectInstance> originList = new ArrayList<>(List.copyOf(origin));
    List<StatusEffectInstance> addList = new ArrayList<>(List.copyOf(add));
    List<StatusEffectInstance> newList = new ArrayList<>();

    for (StatusEffectInstance originEffect : origin) {

      for (StatusEffectInstance addEffect : add) {

        if (originEffect.getEffectType().equals(addEffect.getEffectType())) {

          int duration = originEffect.getDuration() + addEffect.getDuration();
          int amplifier = Math.max(originEffect.getAmplifier(), addEffect.getAmplifier());
          boolean ambient = originEffect.isAmbient();
          boolean showParticles = originEffect.shouldShowParticles();
          boolean showIcon = originEffect.shouldShowIcon();

          newList.add(new StatusEffectInstance(originEffect.getEffectType(), duration, amplifier, ambient, showParticles, showIcon));

          originList.remove(originEffect);
          addList.remove(addEffect);

        }

      }

    }

    newList.addAll(originList);
    newList.addAll(addList);
    return newList;
  }

}
